﻿using System;
using System.Data;

namespace JESAI.DistributedLock.MySql;

/// <summary>
/// 实现 <see cref="IDistributedLockProvider"/> 以获取 <see cref="MySqlDistributedLock"/>
/// </summary>
public sealed class MySqlDistributedSynchronizationProvider : IDistributedLockProvider
{
    private readonly Func<string, bool, MySqlDistributedLock> _lockFactory;

    /// <summary>
    /// 构造一个与<paramref name="connectionString"/>和 <paramref name="options"/>连接的提供程序。
    /// </summary>
    public MySqlDistributedSynchronizationProvider(string connectionString, Action<MySqlConnectionOptionsBuilder>? options = null)
    {
        if (connectionString == null) { throw new ArgumentNullException(nameof(connectionString)); }

        this._lockFactory = (name, exactName) => new MySqlDistributedLock(name, connectionString, options, exactName);
    }

    /// <summary>
    /// 构造一个与以下对象连接的提供程序 <paramref name="connection"/>.
    /// </summary>
    public MySqlDistributedSynchronizationProvider(IDbConnection connection)
    {
        if (connection == null) { throw new ArgumentNullException(nameof(connection)); }

        this._lockFactory = (name, exactName) => new MySqlDistributedLock(name, connection, exactName);
    }

    /// <summary>
    /// 构造一个与以下对象连接的提供程序 <paramref name="transaction"/>.
    /// </summary>
    public MySqlDistributedSynchronizationProvider(IDbTransaction transaction)
    {
        if (transaction == null) { throw new ArgumentNullException(nameof(transaction)); }

        this._lockFactory = (name, exactName) => new MySqlDistributedLock(name, transaction, exactName);
    }

    /// <summary>
    /// 使用提供的<paramref name="name"/>创建一个<see cref="MySqlDistributedLock"/>。除非指定了<paramref name="exactName"/> ，否则将转义/散列无效名称。
    /// </summary>
    public MySqlDistributedLock CreateLock(string name, bool exactName = false) => this._lockFactory(name, exactName);

    IDistributedLock IDistributedLockProvider.CreateLock(string name) => this.CreateLock(name);
}
